<script lang="ts" setup>
import { ref } from "vue";

interface Props {
    label?: string;
    type?: "text" | "number" | "date" | "datetime-local" | "time" | "select" | "radio" | "checkbox" | "group" | "password" | "textarea" | "image-file";
    modelValue?: any;
    autocomplete?: boolean;
    inputText?: string;
    placeholder?: string;
    prefixIcon?: string;
    suffixButton?: string;
    suffixButtonDisabled?: boolean;
    options?: { label: string; value: string | number }[];
}
const props = withDefaults(defineProps<Props>(), {
    type: "text",
});
const emits = defineEmits(["update:model-value", "suffix-button-click", "change"]);
const oInput = ref<HTMLInputElement | null>(null);
</script>

<template>
    <div class="my-input">
        <label v-if="props.label" class="label" @click="oInput?.focus()">
            {{ props.label }}
        </label>
        <div :class="{ control: true, [props.type]: true }">
            <slot>
                <template v-if="props.type == 'text' || props.type == 'password' || props.type == 'number' || props.type == 'datetime-local' || props.type == 'time'">
                    <svg v-if="props.prefixIcon" class="icon prefix-icon" aria-hidden="true">
                        <use :xlink:href="'#icon-' + props.prefixIcon"></use>
                    </svg>
                    <input
                        ref="oInput"
                        :type="props.type"
                        :value="props.modelValue"
                        :placeholder="props.placeholder"
                        :autocomplete="props.autocomplete ? 'on' : 'off'"
                        @input="emits('update:model-value', ($event.target as HTMLInputElement).value)"
                    />
                    <button v-if="props.suffixButton" class="suffix-button" :disabled="props.suffixButtonDisabled" @click.stop.prevent="emits('suffix-button-click')">{{ suffixButton }}</button>
                    <ul v-if="props.options?.length">
                        <template v-for="(v, i) in props.options" :key="v.value">
                            <li v-if="props.modelValue === '' || v.value.toString().includes(props.modelValue)" @mousedown.stop="emits('update:model-value', v.value), oInput?.focus(), emits('change', { index: i, option: v })">
                                {{ v.label }}
                            </li>
                        </template>
                    </ul>
                </template>
                <template v-if="props.type == 'select'">
                    <svg v-if="props.prefixIcon" class="icon prefix-icon" aria-hidden="true">
                        <use :xlink:href="'#icon-' + props.prefixIcon"></use>
                    </svg>
                    <input ref="oInput" readonly :value="props.options?.find((v) => v.value === props.modelValue)?.label || props.placeholder" />
                    <svg class="icon suffix-icon" aria-hidden="true">
                        <use xlink:href="#icon-xia"></use>
                    </svg>
                    <ul>
                        <li v-for="(v, i) in props.options" :key="v.value" @mousedown.stop="emits('update:model-value', v.value), emits('change', { index: i, option: v })">{{ v.label }}</li>
                    </ul>
                </template>
                <template v-if="props.type == 'textarea'">
                    <textarea ref="oInput" :value="props.modelValue" :placeholder="props.placeholder" @input="emits('update:model-value', ($event.target as HTMLTextAreaElement).value)"></textarea>
                </template>
                <template v-if="props.type == 'radio'">
                    <label @click.stop>
                        <input type="radio" :checked="props.modelValue" @click.stop="emits('update:model-value', true)" @change="emits('change')" />
                        <span>{{ props.inputText }}</span>
                    </label>
                </template>
                <template v-if="props.type == 'checkbox'">
                    <label @click.stop>
                        <input type="checkbox" :checked="props.modelValue" @click.stop="emits('update:model-value', !props.modelValue)" @change="emits('change')" />
                        <span>{{ props.inputText }}</span>
                    </label>
                </template>
                <template v-if="props.type == 'image-file'">
                    <label @click.stop>
                        <input type="file" @change="emits('change')" />
                        <img :src="props.modelValue" alt="" />
                    </label>
                </template>
            </slot>
        </div>
    </div>
</template>

<style lang="scss" scoped>
.my-input {
    width: 100%;
    display: flex;
    align-items: flex-start;
    min-height: 30px;
    .label {
        flex-shrink: 0;
        margin-right: 10px;
        font-size: 14px;
        line-height: 30px;
        min-width: 80px;
    }
    .control {
        flex: 1;
        min-height: 30px;
        &.text,
        &.password,
        &.number,
        &.datetime-local,
        &.time,
        &.select {
            position: relative;
            height: 30px;
            box-shadow: 0 0 1px 1px var(--color8);
            transition: box-shadow 0.2s;
            display: flex;
            align-items: center;
            border-radius: 2px;
            background-color: var(--color12);
            .prefix-icon {
                margin-left: 6px;
                font-size: 14px;
            }
            input {
                flex: 1;
                margin: 0 6px;
                height: 100%;
                font-size: 14px;
                background-color: transparent;
            }
            .suffix-icon {
                margin-right: 6px;
                font-size: 14px;
                transition: transform 0.2s;
            }
            .suffix-button {
                padding: 0 6px;
                height: 100%;
                color: #fff;
                background-color: var(--primary1);
                &:disabled {
                    background-color: var(--color8);
                }
            }
            ul {
                position: absolute;
                top: 100%;
                left: 0;
                width: 100%;
                max-height: 0;
                overflow: auto;
                background-color: #fff;
                transition: height 0.2s, box-shadow 0.2s;
                background-color: #fff;
                z-index: 9;
                li {
                    padding: 0 10px;
                    height: 30px;
                    font-size: 14px;
                    display: flex;
                    align-items: center;
                    cursor: pointer;
                    transition: background-color 0.2s;
                    &:hover {
                        background-color: var(--primary3);
                    }
                }
            }
            &:focus-within {
                box-shadow: 0 0 3px 1px var(--primary1);
                z-index: 2;
                .icon {
                    color: var(--primary1);
                }
                ul {
                    max-height: 150px;
                    box-shadow: 0 0 3px 1px var(--primary1);
                }
                .suffix-icon {
                    transform: rotate(180deg);
                }
            }
        }
        &.textarea {
            background-color: var(--color12);
            box-shadow: 0 0 1px 1px var(--color8);
            border-radius: 2px;
            transition: box-shadow 0.2s;
            textarea {
                box-sizing: border-box;
                padding: 6px;
                width: 100%;
                min-height: 30px;
                height: 100px;
                display: flex;
                align-items: center;
                font-size: 14px;
                background-color: transparent;
                resize: vertical;
                overflow: hidden;
            }
            &:focus-within {
                box-shadow: 0 0 3px 1px var(--primary1);
                z-index: 2;
            }
        }
        &.checkbox,
        &.radio {
            height: 30px;
            label {
                height: 100%;
                display: flex;
                align-items: center;
                cursor: pointer;
                input {
                    cursor: pointer;
                }
                span {
                    margin-left: 6px;
                    font-size: 14px;
                }
            }
        }
        &.image-file {
            label {
                width: 50px;
                height: 50px;
                box-shadow: 0 0 1px 1px var(--color8);
                transition: box-shadow 0.2s;
                display: flex;
                align-items: center;
                border-radius: 2px;
                cursor: pointer;
                input {
                    display: none;
                }
                img {
                    width: 100%;
                    height: 100%;
                    object-fit: contain;
                }
            }
        }
        &.group {
            display: flex;
            align-items: center;
            flex-wrap: wrap;
            column-gap: 10px;
            .my-input {
                width: auto;
            }
        }
    }
}
</style>
